package com.jier.common.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * @Description:日期工具类
 * @ClassName :com.demo.common.util.DateUtil.java
 * @Author :lijie
 */
public class DateUtil {
    // 日期格式
    public final static String YM = "yyyy-MM";
    public final static String YMD = "yyyy-MM-dd";
    public final static String YMDHMS = "yyyy-MM-dd HH:mm:ss";
    public final static String MDHMS = "MM-dd HH:mm:ss";
    public final static String YMDHMS_ = "yyyy/MM/dd HH:mm:ss";
    public static final String YMDHM = "yyyy-MM-dd HH:mm";
    public static final String YMDCHINESE = "yyyy年MM月dd日";

    public final static int ERA = 0;
    public final static int YEAR = 1;
    public final static int MONTH = 2;
    public final static int WEEK_OF_YEAR = 3;
    public final static int WEEK_OF_MONTH = 4;
    public final static int DATE = 5;
    public final static int DAY = 5;
    public final static int DAY_OF_MONTH = 5;
    public final static int DAY_OF_YEAR = 6;
    public final static int DAY_OF_WEEK = 7;
    public final static int DAY_OF_WEEK_IN_MONTH = 8;
    public final static int HOUR = 10;
    public final static int HOUR_OF_DAY = 11;
    public final static int MINUTE = 12;
    public final static int SECOND = 13;
    public final static int MILLISECOND = 14;

    /**
     * 将日期转换为 yyyy年MM月dd日 格式的字符串
     *
     * @param date 需要转换的日期
     * @return 字符串
     */
    public static String formatYMDCHINESE(Date date) {
        return DateUtil.format(date, DateUtil.YMDCHINESE);
    }

    /**
     * 将日期转换为 MM-dd HH:mm:ss 格式的字符串
     *
     * @param date 需要转换的日期
     * @return 字符串
     */
    public static String formatMDHMS(Date date) {
        return DateUtil.format(date, DateUtil.MDHMS);
    }

    /**
     * 将日期转换为 yyyy-MM 格式的字符串
     *
     * @param date 需要转换的日期
     * @return 字符串
     */
    public static String formatYM(Date date) {
        return DateUtil.format(date, DateUtil.YM);
    }

    /**
     * 将日期转换为 yyyy-MM-dd 格式的字符串
     *
     * @param date 需要转换的日期
     * @return 字符串
     */
    public static String format(Date date) {
        return DateUtil.format(date, DateUtil.YMD);
    }

    /**
     * @param date 需要转换的日期
     * @return 日期字符串
     * @Description: 将日期转换为字符串，格式为"yyyy-MM-dd"
     * @MethodName :format
     * @Author :lijie
     */
    public static String formatF(Date date) {
        return DateUtil.format(date, DateUtil.YMDHMS_);
    }

    /**
     * @param date
     * @return
     * @Description: 转成YMDHM格式
     */
    public static String formatYMDHM(Date date) {
        return DateUtil.format(date, DateUtil.YMDHM);
    }

    /**
     * @param date
     * @return
     * @Description: 转成YMDHM格式
     */
    public static String parseFormatYMDHM(String date) {
        Date d = DateUtil.parse(date, DateUtil.YMDHM);
        return DateUtil.format(d, DateUtil.YMDHM);
    }

    /**
     * @param date 需要转换的日期
     * @return 日期字符串
     * @Description: 将日期转换为字符串，格式为"yyyy-MM-dd HH:mm:ss"
     * @MethodName :formatTime
     * @Author :lijie
     */
    public static String formatTime(Date date) {
        return DateUtil.format(date, DateUtil.YMDHMS);
    }

    /**
     * @param date    需要转换的日期
     * @param pattern 转换格式
     * @return 日期字符串
     * @Description: 将日期转换为字符串，可自定义格式
     * @MethodName :format
     * @Author :lijie
     */
    public static String format(Date date, String pattern) {
        DateFormat df = new SimpleDateFormat(pattern);
        if (date != null) {
            return df.format(date);
        }
        return null;
    }

    /**
     * @param strDate
     * @return
     * @Description: 将字符串转换为日期，格式为"yyyy-MM"
     * @MethodName :parse
     * @Author :lijie
     */
    public static Date parseYM(String strDate) {
        return parse(strDate, DateUtil.YM);
    }

    /**
     * @param strDate
     * @return
     * @Description: 将字符串转换为日期，格式为"yyyy-MM-dd"
     * @MethodName :parse
     * @Author :lijie
     */
    public static Date parse(String strDate) {
        return parse(strDate, DateUtil.YMD);
    }

    /**
     * @param strDate
     * @return
     * @Description: 将字符串转换为日期，格式为"yyyy-MM-dd HH:mm:ss"
     * @MethodName :parseTime
     * @Author :lijie
     */
    public static Date parseTime(String strDate) {
        return parse(strDate, DateUtil.YMDHMS);
    }


    public static Date parseTimeYMDHM(String strDate) {
        return parse(strDate, DateUtil.YMDHM);
    }

    /**
     * @param strDate
     * @param pattern
     * @return
     * @Description: 将字符串转换为日期，自定义格式
     * @MethodName :parse
     * @Author :lijie
     */
    public static Date parse(String strDate, String pattern) {
        DateFormat df = new SimpleDateFormat(pattern);
        try {
            return df.parse(strDate);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * @param d1
     * @param d2
     * @return
     * @Description:判断 d1是否早于d2
     * @MethodName :before
     * @Author :lijie
     */
    public static boolean before(Date d1, Date d2) {
        return d1.before(d2);
    }

    /**
     * @param d1
     * @param d2
     * @return
     * @Description:判断 d1是否晚于d2
     * @MethodName :after
     * @Author :lijie
     */
    public static boolean after(Date d1, Date d2) {
        return d1.after(d2);
    }

    /**
     * @param date  日期
     * @param field 日期改变部分,如DateUtil.YEAR,DateUtil.MONTH。。。
     * @param value 设置的值
     * @return
     * @Description: 设置日期某一部分的值
     * @MethodName :set
     * @Author :lijie
     */
    public static Date set(Date date, int field, int value) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(field, value);
        return cal.getTime();
    }

    /**
     * @param date   日期
     * @param field  日期改变部分,如DateUtil.YEAR,DateUtil.MONTH。。。
     * @param amount 增加/减少的值:正数为增加，负数为减少
     * @return
     * @Description: 增加/减少日期某一部分的值
     * @MethodName :add
     * @Author :lijie
     */
    public static Date add(Date date, int field, int amount) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(field, amount);
        return cal.getTime();

    }

    public static int countMonths(String date1, String date2, String pattern) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);

        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();

        c1.setTime(sdf.parse(date1));
        c2.setTime(sdf.parse(date2));

        int year = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);

        //开始日期若小月结束日期
        if (year < 0) {
            year = -year;
            return year * 12 + c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH);
        }

        return year * 12 + c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);
    }

    /**
     * @param date  日期
     * @param field 日期部分，如DateUtil.YEAR,DateUtil.MONTH。。。
     * @return
     * @Description: 取得日期某一部分最大可能的数值（如某一月的最大天数）
     * @MethodName :getMaximum
     * @Author :lijie
     */
    public static int getMaximum(Date date, int field) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.getMaximum(field);
    }

    /**
     * @param year
     * @param month
     * @param date
     * @return
     * @Description: 通过设置年月日来得到日期
     * @MethodName :getDate
     * @Author :lijie
     */
    public static Date getDate(int year, int month, int date) {
        return getDate(year, month, date, 0, 0, 0);
    }

    /**
     * @param year
     * @param month
     * @param date
     * @param hourOfDay
     * @param minute
     * @return
     * @Description: 通过设置年, 月, 日, 小时, 分来得到日期
     * @MethodName :getDate
     * @Author :lijie
     */
    public static Date getDate(int year, int month, int date, int hourOfDay, int minute) {
        return getDate(year, month, date, hourOfDay, minute, 0);
    }

    /**
     * @param year
     * @param month
     * @param date
     * @param hourOfDay
     * @param minute
     * @param second
     * @return 日期
     * @Description: 通过设置年, 月, 日, 小时, 分，秒来得到日期
     * @MethodName :getDate
     * @Author :lijie
     */
    public static Date getDate(int year, int month, int date, int hourOfDay, int minute, int second) {
        Calendar cal = Calendar.getInstance();
        cal.clear();
        cal.set(year, month, date, hourOfDay, minute, second);
        return cal.getTime();
    }

    /**
     * @param date
     * @return
     * @Description: 得到星期
     * @MethodName :getWeek
     * @Author :lijie
     */
    public static Integer getWeek(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int i = cal.get(Calendar.DAY_OF_WEEK);
        if (i != 1) {
            i--;
        } else {
            i = 7;
        }
        return i;
    }

    /**
     * 通过传入的生日得到具体年龄
     *
     * @param birthday 生日
     * @return 年龄
     */
    public static Integer getAge(Date birthday) {
        Integer result = 0;
        Calendar calendar = Calendar.getInstance();
        if (birthday == null) {
            return 0;
        }
        if (calendar.getTime().after(birthday)) {
            // 获取系统年、月、日
            int sysYear = calendar.get(Calendar.YEAR);
            int sysMonth = calendar.get(Calendar.MONTH) + 1;
            int sysDay = calendar.get(Calendar.DAY_OF_MONTH);
            // 获取用户生日年、月、日
            calendar.setTime(birthday);
            int userYear = calendar.get(Calendar.YEAR);
            int userMonth = calendar.get(Calendar.MONTH) + 1;
            int userDay = calendar.get(Calendar.DAY_OF_MONTH);
            int age = sysYear - userYear;
            // 计算年龄
            if (sysMonth <= userMonth) {
                if (sysMonth == userMonth) {
                    if (sysDay < userDay) {
                        age--;
                    }
                } else {
                    age--;
                }
            }
            result = age;
        }
        return result;
    }

    /**
     * 通过身份证号获取生日
     *
     * @param IDCard
     * @return
     */
    public static Date getBirthdayDate(String IDCard) {
        if (StringUtil.isEmpty(IDCard)) {
            return null;
        }
        String birthdayStr = IDCard.substring(6, 14);
        String year = birthdayStr.substring(0, 4);
        String month = birthdayStr.substring(4, 6);
        String day = birthdayStr.substring(6, 8);
        return parse(year + "-" + month + "-" + day);
    }

    /**
     * 通过年龄计算默认出生日期
     *
     * @param age   年龄
     * @param agedw 年龄单位： 1-年 2-month 3-day 4-hour
     * @return
     */
    public static String getBirthdayDate(int age, int agedw) {
        // 获取现在时间
        Calendar calendar = Calendar.getInstance();
        // 获取年份
        int year = calendar.get(Calendar.YEAR);
        // 获取月份
        int month = calendar.get(Calendar.MONTH) + 1;
        // 获取日期
        int day = calendar.get(Calendar.DATE);
        // 获取小时
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        // 获取分钟
        int minute = calendar.get(Calendar.MINUTE);
        // 获取秒钟
        int second = calendar.get(Calendar.SECOND);
        String date = null;
        if (agedw == 1) {
            year = year - age;
        }
        if (agedw == 2) {
            month = month - age;
        }
        if (agedw == 3) {
            day = day - age;
        }
        if (agedw == 4) {
            hour = hour - age;
        }
        // 拼接日期
        date = year + "-" + (month < 10 ? "0" + month : month) + "-" + (day < 10 ? "0" + day : day);
        // 拼接时间
        String time = (hour < 10 ? "0" + hour : hour) + ":"
                + (minute < 10 ? "0" + minute : minute) + ":"
                + (second < 10 ? "0" + second : second);
        // 拼接日期和时间
        String dateTime = date + " " + time;
        return dateTime;
    }


    /**
     * 获取时间差
     *
     * @param beforeDate
     * @param AfterDate
     * @param type
     * @return
     */
    public static double getTimeDiffer(Date beforeDate, Date AfterDate, Integer type) {
        BigDecimal tmp = new BigDecimal(AfterDate.getTime() - beforeDate.getTime());
        BigDecimal divisor;
        switch (type) {
            case DAY:
                divisor = new BigDecimal(1000 * 60 * 60 * 24);
                break;
            case HOUR:
                divisor = new BigDecimal(1000 * 60 * 60);
                break;
            case MINUTE:
                divisor = new BigDecimal(1000 * 60);
                break;
            default:
                divisor = new BigDecimal(1000);
                break;
        }
        double result = tmp.divide(divisor, 2, RoundingMode.FLOOR).doubleValue();
        return result;
    }

    public static long getDistanceTime(Date str1, Date str2) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date one;
        Date two;
        long day = 0;
        long hour = 0;
        long min = 0;
        long sec = 0;

        long time1 = str1.getTime();
        long time2 = str2.getTime();
        long diff;
        if (time1 < time2) {
            diff = time2 - time1;
        } else {
            diff = time1 - time2;
        }
        day = diff / (24 * 60 * 60 * 1000);
        hour = (diff / (60 * 60 * 1000) - day * 24);
        min = ((diff / (60 * 1000)) - day * 24 * 60 - hour * 60);
        return day * 60 * 60 + hour * 60 + min;
    }
}
